
#include "bsp.h"


/***************************************************************************************************
 * @fn		queue_init
 *
 * @brief   初始化环形队列
 *
 * @param	q   队列结构体    
 * @param   buf     队列缓冲区 
 * @param   length  队列长度(总容量)
 *
 * @return	TRUE 初始化成功;  FALSE 初始化失败
 */
BOOL queue_init(queue_t *q, queue_elem_t *buf, int16_t length)
{
    /* 传入参数不合理，返回一个错误 */
    if (q == NULL || buf == NULL || length == 0)
    {
        return FALSE;
    }

    /* 队列参数初始化 */
    q->w_index = 0;
    q->r_index = 0;
    q->cur_len = 0;
    q->max_len = length;
    q->buffer  = buf;

    return TRUE;
}

/***************************************************************************************************
 * @fn		queue_clear
 *
 * @brief   清队列
 *
 * @param	q  队列结构体  
 *
 * @return	TRUE 清队列成功;  FALSE 清队列失败
 */
BOOL queue_clear(queue_t *q)
{
    /* 传入的指针参数不能为空 */
    if (q == NULL)
    {
        return FALSE;
    }

    /* 清零队列读、写指针，清零队列当前元素个数 */
    q->w_index = 0;
    q->r_index = 0;
    q->cur_len = 0;

    return TRUE;
}

/***************************************************************************************************
 * @fn		queue_is_empty
 *
 * @brief   判断队列是否为空
 *
 * @param	q  队列结构体  
 *
 * @return	TRUE 队列为空;  FALSE 队列非空
 */
BOOL queue_is_empty(queue_t *q)
{
    /* 传入的指针参数不能为空 */
    if (q == NULL)
    {
        return FALSE;
    }
    
    if (0U == q->cur_len)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

/***************************************************************************************************
 * @fn		queue_is_full
 *
 * @brief   判断队列是否已满
 *
 * @param	q  队列结构体  
 *
 * @return	TRUE 队列满;  FALSE 队列尚未满
 */
BOOL queue_is_full(queue_t *q)
{
    /* 传入的指针参数不能为空 */
    if (q == NULL)
    {
        return FALSE;
    }

    /* 队列满：当前元素个数等于或者超过最大长度 */
    if (q->cur_len >= q->max_len)
    {
        return TRUE;
    }
    else
    {
        return FALSE; 
    }
}

/***************************************************************************************************
 * @fn      queue_length
 *
 * @brief   获取队列当前元素个数
 *
 * @param	q  队列结构体  
 *
 * @return	队列当前元素个数
 */
int16_t queue_length(queue_t *q)
{   
    /* 传入的指针参数不能为空 */
    if (q == NULL)
    {
        return 0;
    }
        
    return (q->cur_len);
}

/***************************************************************************************************
 * @fn      queue_unused
 *
 * @brief   队列中未使用的元素个数
 *
 * @param	q  队列结构体  
 *
 * @return	队列未使用的元素个数
 */
int16_t queue_unused(queue_t * q)
{
    /* 传入的指针参数不能为空 */
   if (q == NULL)
   {
        return 0;
   }
        
    return (q->max_len - q->cur_len);
}

/***************************************************************************************************
 * @fn		queue_enter
 *
 * @brief   队列入队操作
 *
 * @param	q  队列结构体  
 * @param	data  写入的数据 
 *
 * @return	成功写入的数据个数
 */
int16_t queue_enter(queue_t *q, queue_elem_t data)
{
    /* 传入的指针不能为空 */
    if (q == NULL)
    {
        return 0;
    }

    /* 如果队列已经满，直接退出 */
    if (queue_is_full(q) == TRUE)
    {
        return 0;
    }

    q->buffer[q->w_index] = data;  /* 将待入队的数据写入队列 */
    q->w_index++;  /* 写指针自增，即指向队尾元素的下一个位置 */

    /* 写指针不能越界 */
    if (q->w_index >= q->max_len)
    {
        /* 如果元素的下一个位置为max_len，则w_index归零 */
        q->w_index = 0;  
    }

    q->cur_len++;  /* 队列当前元素个数加一 */

    return 1;
}

/***************************************************************************************************
 * @fn		queue_enter_buffer
 *
 * @brief   队列入队操作
 *
 * @param	q  队列结构体  
 * @param	buf  写入的数据 
 * @param	len  写入的数据长度 
 *
 * @return	成功写入的数据个数
 */
int16_t queue_enter_buffer(queue_t *q, queue_elem_t *buf, int16_t len)
{
    int16_t length = 0;  /* 待入队的元素有len个，length从0增加到len-1 */

    if (q == NULL || buf == NULL || len == 0)
    {
        return 0;
    }

    /* 写入操作：队列未满，则可以写入 */
    while ((queue_is_full(q) == FALSE) && (length < len))
    {
        q->buffer[q->w_index] = buf[length];  /* 将待入队的第lenght个数据写入队列 */
        q->w_index++;  /* 写指针自增，即指向队尾元素的下一个位置 */

        /* 写指针不能越界 */
        if (q->w_index >= q->max_len)
        {
            /* 如果元素的下一个位置为max_len，则w_index归零 */
            q->w_index = 0;  
        }

        length++;
        q->cur_len++;  /* 队列当前元素个数加一 */
    }

    return length;
}

/***************************************************************************************************
 * @fn		queue_delete
 *
 * @brief   队列出队操作
 *
 * @param	q  队列结构体  
 * @param	buf  读取的数据 
 *
 * @return	成功读取的数据个数
 */
int16_t queue_delete(queue_t *q, queue_elem_t *data)
{
    /* 传入的指针参数不能为空 */
    if (q == NULL && data == NULL)
    {
        return 0;
    }

    /* 队列为空，直接退出 */
    if (queue_is_empty(q) == TRUE)
    {
        return 0;
    }

    *data = q->buffer[q->r_index]; 
    q->r_index++;

    /* 读指针不能越界 */
    if (q->r_index >= q->max_len)
    {
        /* 如果元素的下一个位置为max_len，则r_index归零 */
        q->r_index = 0;  
    }

    q->cur_len--;  /* 当前队列中的元素总数减一 */

    return 1;
}

/***************************************************************************************************
 * @fn		queue_delete_buffer
 *
 * @brief   队列出队操作
 *
 * @param	q  队列结构体  
 * @param	buf  读取的数据 
 * @param	len  读取的数据长度 
 *
 * @return	成功读取的数据个数
 */
int16_t queue_delete_buffer(queue_t *q, queue_elem_t *buf, int16_t len)
{
    int16_t length = 0;  /* 期望取出len个元素，最终能取出length个元素 */

    if (q == NULL || buf == NULL || len == 0)
    {
        return 0;
    }

    /* 读操作：队列非空，则可以读取 */
    while ((queue_is_empty(q) == FALSE) && (length < len))
    {
        buf[length] = q->buffer[q->r_index]; 
        q->r_index++;

        /* 读指针不能越界 */
        if (q->r_index >= q->max_len)
        {
            /* 如果元素的下一个位置为max_len，则r_index归零 */
            q->r_index = 0;   
        }

        length++;
        q->cur_len--;  /* 当前队列中的元素总数减一 */
    }

    return length;
}


